1 /* 2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021 3 License: [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License]. 4 Authors: Marcelo S. N. Mancini 5 6 Copyright Marcelo S. N. Mancini 2018 - 2021. 7 Distributed under the CC BY-4.0 License. 8 (See accompanying file LICENSE.txt or copy at 9 https://creativecommons.org/licenses/by/4.0/ 10 */ 11 module hip.hiprenderer.backend.d3d.d3dtexture; 12 version(Windows): 13 version(DirectX): 14 import hip.hiprenderer.backend.d3d.d3drenderer; 15 public import hip.api.renderer.texture; 16 17 import hip.image; 18 import directx.d3d11; 19 import hip.error.handler; 20 21 22 private __gshared ID3D11ShaderResourceView nullSRV = null; 23 private __gshared ID3D11SamplerState nullSamplerState = null; 24 25 class Hip_D3D11_Texture : IHipTexture 26 { 27 ID3D11Texture2D texture; 28 ID3D11ShaderResourceView resource; 29 ID3D11SamplerState sampler; 30 int width, height; 31 float[4] borderColor; 32 int filter = Hip_D3D11_getTextureFilter(TextureFilter.NEAREST, TextureFilter.NEAREST); 33 int wrap = Hip_D3D11_getWrapMode(TextureWrapMode.REPEAT); 34 bool[] slotsBound; 35 36 IHipTexture getBackendHandle(){return this;} 37 this() 38 { 39 import hip.hiprenderer:HipRenderer; 40 slotsBound = new bool[HipRenderer.getMaxSupportedShaderTextures()]; 41 } 42 43 44 bool hasSuccessfullyLoaded(){return width > 0;} 45 46 void setTextureFilter(TextureFilter mag, TextureFilter min) 47 { 48 filter = Hip_D3D11_getTextureFilter(min, mag); 49 updateSamplerState(); 50 } 51 package void updateSamplerState() 52 { 53 D3D11_SAMPLER_DESC desc; 54 desc.Filter = filter; 55 desc.AddressU = wrap; 56 desc.AddressV = wrap; 57 desc.AddressW = wrap; 58 desc.BorderColor = [1, 1, 1, 1]; 59 desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; 60 desc.MinLOD = 0; 61 desc.MaxLOD = D3D11_FLOAT32_MAX; 62 desc.MipLODBias = 0f; 63 desc.MaxAnisotropy = 1; 64 _hip_d3d_device.CreateSamplerState(&desc, &sampler); 65 } 66 public void setWrapMode(TextureWrapMode mode) 67 { 68 wrap = Hip_D3D11_getWrapMode(mode); 69 updateSamplerState(); 70 } 71 72 protected bool loadImpl(in IImage image) 73 { 74 D3D11_TEXTURE2D_DESC desc; 75 // desc.Format = getFromFromSurface(surface); 76 desc.Usage = D3D11_USAGE_IMMUTABLE; 77 desc.CPUAccessFlags = 0; 78 desc.MipLevels = 1; 79 desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 80 desc.Width = width = image.getWidth; 81 desc.Height = height = image.getHeight; 82 83 D3D11_SUBRESOURCE_DATA data; 84 85 const(void)[] pixels; 86 ushort Bpp = 0; 87 int format; 88 89 switch(image.getBytesPerPixel) 90 { 91 case 1: 92 if(image.hasPalette) 93 { 94 pixels = image.convertPalettizedToRGBA(); 95 Bpp = 4; 96 format = DXGI_FORMAT_R8G8B8A8_UNORM; 97 } 98 else 99 { 100 pixels = image.getPixels; 101 Bpp = 1; 102 format = DXGI_FORMAT_R8_UNORM; 103 } 104 break; 105 case 3: 106 case 4: 107 pixels = image.getPixels; 108 Bpp = image.getBytesPerPixel; 109 format = DXGI_FORMAT_R8G8B8A8_UNORM; 110 break; 111 case 2: 112 default: 113 ErrorHandler.assertLazyExit(false, 114 "Unsopported bytes per pixel for D3D11 Texture named '"~image.getName~"'"); 115 } 116 desc.Format = format; 117 data.pSysMem = cast(void*)pixels.ptr; 118 data.SysMemPitch = image.getWidth*Bpp; 119 120 _hip_d3d_device.CreateTexture2D(&desc, &data, &texture); 121 _hip_d3d_device.CreateShaderResourceView(texture, cast(D3D11_SHADER_RESOURCE_VIEW_DESC*)null, &resource); 122 updateSamplerState(); 123 bind(); 124 return false; 125 } 126 127 128 ///256 should be enough too 129 private __gshared Hip_D3D11_Texture[256] boundTextures; 130 131 ///Avoids rebinding to the same sl 132 void bind (int slot = 0) 133 { 134 if(boundTextures[slot] !is this) 135 { 136 _hip_d3d_context.PSSetSamplers(slot, 1, &sampler); 137 _hip_d3d_context.PSSetShaderResources(slot, 1, &resource); 138 boundTextures[slot] = this; 139 } 140 } 141 142 void unbind (int slot = 0) 143 { 144 if(boundTextures[slot] is this) 145 { 146 _hip_d3d_context.PSSetSamplers(slot, 1, &nullSamplerState); 147 _hip_d3d_context.PSSetShaderResources(slot, 1, &nullSRV); 148 boundTextures[slot] = null; 149 } 150 } 151 152 int getWidth() const {return width;} 153 int getHeight() const {return height;} 154 155 } 156 157 158 pure int Hip_D3D11_getTextureFilter(TextureFilter min, TextureFilter mag) 159 { 160 with(TextureFilter) 161 { 162 switch(min) 163 { 164 case LINEAR: 165 if(mag == LINEAR) 166 return D3D11_FILTER_MIN_MAG_MIP_LINEAR; 167 break; 168 case NEAREST: 169 if(mag == LINEAR) 170 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; 171 return D3D11_FILTER_MIN_MAG_MIP_POINT; 172 case NEAREST_MIPMAP_LINEAR: 173 return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; 174 default:break; 175 } 176 } 177 return D3D11_FILTER_MIN_MAG_MIP_LINEAR; 178 } 179 180 pure int Hip_D3D11_getWrapMode(TextureWrapMode mode) 181 { 182 switch(mode) with(TextureWrapMode) 183 { 184 case CLAMP_TO_EDGE: 185 return D3D11_TEXTURE_ADDRESS_CLAMP; 186 case CLAMP_TO_BORDER: 187 return D3D11_TEXTURE_ADDRESS_BORDER; 188 case REPEAT: 189 return D3D11_TEXTURE_ADDRESS_WRAP; 190 case MIRRORED_REPEAT: 191 return D3D11_TEXTURE_ADDRESS_MIRROR; 192 case MIRRORED_CLAMP_TO_EDGE: 193 return D3D11_TEXTURE_ADDRESS_MIRROR_ONCE; 194 case UNKNOWN: 195 default: 196 return D3D11_TEXTURE_ADDRESS_WRAP; 197 } 198 }